package com.cloud.point.concurrent.general;

/**
 * happens-before原则
 *
 * @author 24373
 * @version 1.0
 * @date 2024-06-11 17:34
 */
public class TestHappensBefore {

    public static void main(String[] args) throws InterruptedException {
        testH1();
        testH2();
        testH3();
        testH4();
        testH5();
    }

    static int k;

    /**
     * 线程 t1 打断 t2（interrupt）前对变量的写，对于其他线程得知 t2 被打断后对变量的读可见
     * （通过t2.interrupted 或 t2.isInterrupted）
     */
    private static void testH5() {
        Thread t2 = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println(k);
                    break;
                }
            }
        }, "t2");
        t2.start();

        new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            k = 10;
            t2.interrupt();
        }, "t1").start();

        while (!t2.isInterrupted()) {
            Thread.yield();
        }
        System.out.println(k);
    }

    static int n;

    /**
     * 线程结束前对变量的写，对其它线程得知它结束后的读可见（比如其它线程调用 t1.isAlive() 或 t1.join()等待它结束）
     */
    private static void testH4() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            n = 10;
        }, "t1");
        t1.start();
        t1.join();
        System.out.println(n);
    }

    static int z;

    /**
     * 线程 start 前对变量的写，对该线程开始后对该变量的读可见
     */
    private static void testH3() {
        z = 10;
        new Thread(() -> {
            System.out.println(z);
        }, "t2").start();
    }

    volatile static int y;

    /**
     * 线程对 volatile 变量的写，对接下来其它线程对该变量的读可见
     */
    private static void testH2() {
        new Thread(() -> {
            y = 10;
        }, "t1").start();

        new Thread(() -> {
            System.out.println(y);
        }, "t2").start();

    }

    static int x;
    static Object m = new Object();

    /**
     * 线程解锁 m 之前对变量的写，对于接下来对 m 加锁的其它线程对该变量的读可见
     */
    private static void testH1() {
        new Thread(() -> {
            synchronized (m) {
                x = 10;
            }
        }, "t1").start();

        new Thread(() -> {
            synchronized (m) {
                System.out.println(x);
            }
        }, "t2").start();
    }

}
